package zeronet

import (
	"bytes"
	"encoding/json"
	"golang.org/x/net/websocket"
	"log"
)

type Msg struct {
	Cmd    string      `json:"cmd"`
	Id     uint64      `json:"id"`
	To     uint64      `json:"to"`
	Params interface{} `json:"params"`
	Result interface{} `json:"result"`
}

type zeroSocket struct {
	origin string
	url    string
	ws     *websocket.Conn
	buffer *bytes.Buffer
	temp   []byte
	id     uint64
}

func NewZeroSocket(origin, url string) *zeroSocket {
	z := &zeroSocket{
		origin: origin,
		url:    url,
		temp:   make([]byte, 1024),
		buffer: bytes.NewBuffer(make([]byte, 1024*4)),
		id:     0,
	}

	z.OnOpen()
	return z
}

func (self *zeroSocket) OnClose() {
	_ = self.ws.Close()
}

func (self *zeroSocket) OnOpen() {
	ws, err := websocket.Dial(self.url, "", self.origin)
	if err != nil {
		log.Fatal(err)
	}
	self.ws = ws
}

func (self *zeroSocket) Send(m *Msg) *Msg {
	m.Id = self.id
	self.id++
	self.buffer.Reset()
	b, _ := json.Marshal(m)
	if _, err := self.ws.Write(b); err != nil {
		log.Fatal(err)
	}

	var nm *Msg
	rd, err := self.ws.NewFrameReader()
	if err != nil {
		log.Println(err)
	}
	for {
		n, err := rd.Read(self.temp)
		_, _ = self.buffer.Write(self.temp[:n])
		if err != nil {
			break
		}
	}

	bs := self.buffer.Bytes()
	err = json.Unmarshal(bs, &nm)
	if err != nil {
		log.Println(err)
	}
	return nm
}
